// 运行方式：在build中make
#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include"dir.h"
#include"doublelist.h"

#include "lv_my_font.h"

#define BLOCK_SIZE 30
#define SUB_SIZE (BLOCK_SIZE/4)
#define EMPTY 0XFF

// 全局互斥锁，保护游戏状态访问
pthread_mutex_t game_mutex;
// 游戏结束标志
bool game_over = false;

//方块形状
const uint8_t THTROMINOS[7][4][4]={
    {//j
        {0,0,1,0},
        {1,1,1,0},
        {0,0,0,0},
        {0,0,0,0}
    },
    {
        {1,0,0,0},
        {1,1,1,0},
        {0,0,0,0},
        {0,0,0,0}
    },
    {
        {0,0,0,0},
        {1,1,1,1},
        {0,0,0,0},
        {0,0,0,0}
    },
    {
        {0,1,1,0},
        {0,1,1,0},
        {0,0,0,0},
        {0,0,0,0}
    },
    {
        {0,1,0,0},
        {1,1,1,0},
        {0,0,0,0},
        {0,0,0,0}
    },
    {
        {0,1,1,0},
        {1,1,0,0},
        {0,0,0,0},
        {0,0,0,0}
    },
    {
        {1,1,0,0},
        {0,1,1,0},
        {0,0,0,0},
        {0,0,0,0}
    }
};

//图片路径
const char *BLOCK_IMAGES[7]={
    "A:L.bmp",
    "A:J.bmp",
    "A:I.bmp",
    "A:O.bmp",
    "A:T.bmp",
    "A:S.bmp",
    "A:Z.bmp"
};

typedef struct
{
    //游戏状态
    uint8_t board[20][10];//方块容器总共10*20个格子
    int current_piece;//当前的方块
    int next_piece;//下一个方块
    //方块在20*10个格子的位置（x[0-9],y[0-19]）和旋转状态（4种[0,1,2,3]）
    int x,y,rotation;
    int bag[7];
    int bag_index;

    //游戏数据
    uint32_t score;//当前分数
    uint16_t lines;//消除行数
    uint8_t level;//速度
    uint32_t fall_speed;
}GameState;

typedef struct
{
    lv_obj_t *game_area;
    lv_obj_t *next_block;//下一个方块的预览
    lv_obj_t *score_label;
    lv_obj_t *level_label;
    lv_obj_t *lines_label;

    //方块图片对象(显示)
    lv_obj_t *block_imgs[20][10];
}GameUI;

GameState game;
GameUI ui;


lv_obj_t *my_lv_init_button(lv_obj_t *parent, int x, int y, int w, int h, int color1, int color2, const char *text);

// 渲染定时器回调
static void render_timer_cb(lv_timer_t *timer);
// 游戏线程函数
static void *game_thread_func(void *arg);

//游戏初始化
void game_init();
void create_ui();
//旋转当前的方块
void rotate_piece();
//检查方块状态
bool check_collision(int new_x, int new_y, int new_rotation);
int get_block_pos(int* bx, int* by, int x, int y, int rotation, int piece_type);
//锁住方块（当方块触地或者接触到其他已经固定好的方块时）
void lock_piece();
//清除满了格子的一行
void clear_lines();
void update_game();
void render();
void update_next_preview();
int get_next_from_bag();
void spawn_new_piece();
bool move_piece(int dx,int dy);
//4个按键
static void my_but1_event_cb(lv_event_t *e);
static void my_but2_event_cb(lv_event_t *e);
static void my_but3_event_cb(lv_event_t *e);
static void my_but4_event_cb(lv_event_t *e);


int main(int argc,char *argv[])
{
    // 初始化互斥锁
    pthread_mutex_init(&game_mutex, NULL);

    lv_init();

    /*Linux frame buffer device init*/
    lv_display_t *disp = lv_linux_fbdev_create();
    lv_linux_fbdev_set_file(disp, "/dev/fb0");

    // 初始化触摸屏
    lv_indev_t *indev = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event6");

    // 初始化游戏状态
    pthread_mutex_lock(&game_mutex);
    game_init();
    pthread_mutex_unlock(&game_mutex);

    // 创建UI（主线程）
    create_ui();
    lv_display_set_flush_wait_cb(disp, NULL);

    // 创建渲染定时器（主线程，负责UI更新）
    lv_timer_t *render_timer = lv_timer_create(render_timer_cb, 50, NULL);
    lv_timer_set_repeat_count(render_timer, -1);

    // 创建游戏线程（负责逻辑更新）
    pthread_t game_thread;
    pthread_create(&game_thread, NULL, game_thread_func, NULL);

    /*Handle LVGL tasks*/
   while (1) {
    lv_timer_handler();
    usleep(5000);

    pthread_mutex_lock(&game_mutex);
    bool should_exit = game_over;
    pthread_mutex_unlock(&game_mutex);

    if(should_exit) {
        // 安全地显示游戏结束画面
        lv_obj_t *img = lv_img_create(lv_scr_act());
        lv_img_set_src(img, "A:game.bmp");
        lv_obj_center(img);
        
        // 强制刷新界面
        for(int i = 0; i < 3; i++) {
            lv_timer_handler();
            usleep(10000);
        }
        
        // 确保资源释放
        pthread_mutex_destroy(&game_mutex);
        exit(0);
    }
}
   
    return 0;
}


// 创建一个按钮
lv_obj_t *my_lv_init_button(lv_obj_t *parent, int x, int y, int w, int h, int color1, int color2, const char *text)
{
    // 创建按钮
    lv_obj_t *but = lv_button_create(parent);

    // 设置按钮的大小和位置等属性
    lv_obj_set_size(but, w, h);
    lv_obj_set_pos(but, x, y);

    // 按钮样式
    static lv_style_t but_style;
    lv_style_init(&but_style);
    lv_style_set_bg_color(&but_style, lv_color_hex(color1));
    lv_style_set_text_color(&but_style, lv_color_hex(color2));
    lv_style_set_text_font(&but_style, &lv_font_montserrat_28);

    // 添加样式
    lv_obj_add_style(but, &but_style, LV_STATE_DEFAULT);

    // 给按钮添加标签
    lv_obj_t *lab = lv_label_create(but);
    lv_label_set_text(lab, text);

    return but;
}

//游戏初始化
void game_init()
{
    memset(game.board,EMPTY,sizeof(game.board));

    game.score=0;
    game.level=0;
    game.lines=0;
    game.fall_speed=1000;

    srand(time(NULL));
    game.current_piece=rand()%7;
    game.next_piece=rand()%7;
    game.x=3;
    game.y=-1;//顶部外出现
    game.rotation=0;

    for(int i=0;i<7;i++)
    {
        game.bag[i]=i;
    }
    game.bag_index=7;
    game.current_piece=get_next_from_bag();
    game.next_piece=get_next_from_bag();
}

//随机下一个方块
int get_next_from_bag()
{
    if(game.bag_index>=7)
    {
        for(int i=6;i>0;i--)
        {
            int j=rand()%(i+1);
            int temp=game.bag[j];
            game.bag[j]=game.bag[i];
            game.bag[i]=temp;
        }
        game.bag_index=0;
    }
    return game.bag[game.bag_index++];
}

// 游戏线程函数：处理自动下落逻辑
static void *game_thread_func(void *arg) {
   while(1) {
        pthread_mutex_lock(&game_mutex);
        if(game_over) {
            pthread_mutex_unlock(&game_mutex);
            break;
        }
        bool need_render = false;
        // 只更新游戏状态，不操作UI
        if(!move_piece(0,1)) {
            lock_piece();
            clear_lines();
            spawn_new_piece();
        }
        
        uint32_t sleep_ms = game.fall_speed;
        pthread_mutex_unlock(&game_mutex);

        if(need_render) {
            lv_timer_handler();
        }
        
        usleep(sleep_ms * 1000);
    }
    return NULL;
}

// 渲染定时器回调：更新UI（主线程执行）
static void render_timer_cb(lv_timer_t *timer) {
    pthread_mutex_lock(&game_mutex);
    
    // 只更新数据，不直接操作UI
    static uint32_t last_score = 0;
    static uint16_t last_lines = 0;
    static uint8_t last_level = 0;
    static int last_next_piece = -1;
    
    if(game.score != last_score) {
        char score_str[20];
        sprintf(score_str,"score:%lu",game.score);
        lv_label_set_text(ui.score_label,score_str);
        last_score = game.score;
    }
    
    if(game.lines != last_lines) {
        char lines_str[20];
        sprintf(lines_str,"lines:%u",game.lines);
        lv_label_set_text(ui.lines_label,lines_str);
        last_lines = game.lines;
    }
    
    int current_level = (game.lines/10)+1;
    if(current_level != last_level) {
        char level_str[20];
        sprintf(level_str,"speed:%d",current_level);
        lv_label_set_text(ui.level_label,level_str);
        last_level = current_level;
    }
    
    if(game.next_piece != last_next_piece) {
        update_next_preview();
        last_next_piece = game.next_piece;
    }
    
    render();
    
    pthread_mutex_unlock(&game_mutex);
}

//游戏逻辑更新
void update_game()
{
    if(!move_piece(0,1))//如果方块无法下移
    {
        lock_piece();   // 锁定当前方块
        clear_lines();  // 清除满行
        spawn_new_piece();  // 生成新方块
    }
}

void render()
{
    // 隐藏所有方块
    for(int y=0;y<20;y++)
    {
        for(int x=0;x<10;x++)
        {
            lv_obj_add_flag(ui.block_imgs[y][x],LV_OBJ_FLAG_HIDDEN);
        }
    }

    // 绘制已锁定的方块
    for(int y=0;y<20;y++)
    {
        for(int x=0;x<10;x++)
        {
            if(game.board[y][x]!=EMPTY)//有方块
            {
                lv_img_set_src(ui.block_imgs[y][x],BLOCK_IMAGES[game.board[y][x]]);
                lv_obj_clear_flag(ui.block_imgs[y][x],LV_OBJ_FLAG_HIDDEN);
            }
        }
    }

    // 绘制当前活动方块
    for(int py=0;py<4;py++)
    {
        for(int px=0;px<4;px++)
        {
            int block_value;
            switch (game.rotation % 4) {
                case 0: 
                    block_value = THTROMINOS[game.current_piece][py][px]; 
                    break;
                case 1:
                    block_value = THTROMINOS[game.current_piece][px][3 - py];
                    break;
                case 2: 
                    block_value = THTROMINOS[game.current_piece][3 - py][3 - px]; 
                    break;
                case 3: 
                    block_value = THTROMINOS[game.current_piece][3 - px][py];
                    break;
            }
            if (block_value) {
                int bx=game.x+px;
                int by=game.y+py;
                if(by>=0&&by<20&&bx>=0&&bx<10)//在有效区域内
                {
                    lv_img_set_src(ui.block_imgs[by][bx],BLOCK_IMAGES[game.current_piece]);
                    lv_obj_clear_flag(ui.block_imgs[by][bx],LV_OBJ_FLAG_HIDDEN);
                }
            }
        }
    }

    // 更新分数、等级、行数显示
    char score_str[20];
    sprintf(score_str,"score:%lu",game.score);
    lv_label_set_text(ui.score_label,score_str);

    char level_str[20];
    int current_speed=game.lines/10+1;
    sprintf(level_str,"speed:%d",current_speed);
    lv_label_set_text(ui.level_label,level_str);

    char lines_str[20];
    sprintf(lines_str,"lines:%u",game.lines);
    lv_label_set_text(ui.lines_label,lines_str);

    update_next_preview();
}

//旋转当前的方块
void rotate_piece()
{
   int new_rotation = (game.rotation + 1) % 4;
    
    // 尝试旋转，如果碰撞则尝试左右微调
    for (int offset = 0; offset <= 2; offset++) {
        if (!check_collision(game.x + offset, game.y, new_rotation)) {
            game.x += offset;
            game.rotation = new_rotation;
            return;
        }
        if (!check_collision(game.x - offset, game.y, new_rotation)) {
            game.x -= offset;
            game.rotation = new_rotation;
            return;
        }
    }
    
    // 尝试上下微调（针对I型方块）
    if (game.current_piece == 2) {
        if (!check_collision(game.x, game.y + 1, new_rotation)) {
            game.y += 1;
            game.rotation = new_rotation;
            return;
        }
    }
}

void create_ui()
{
    //主游戏区
    ui.game_area=lv_obj_create(lv_screen_active());
    lv_obj_set_size(ui.game_area,11*BLOCK_SIZE,21*BLOCK_SIZE);
    lv_obj_align(ui.game_area,LV_ALIGN_LEFT_MID,10,0);
    lv_obj_set_style_bg_color(ui.game_area,lv_color_hex(0xC0C0C0),0);
    lv_obj_set_style_bg_opa(ui.game_area, LV_OPA_COVER, 0);
    lv_obj_clear_flag(ui.game_area, LV_OBJ_FLAG_SCROLLABLE);

    // 标题
    lv_obj_t *lab = lv_label_create(lv_screen_active());
    lv_obj_set_size(lab, 400, 200);
    lv_obj_set_pos(lab, 400, 40);
    lv_label_set_text(lab, "俄罗斯方块");
    static lv_style_t lab_style;
    lv_style_init(&lab_style);
    lv_style_set_bg_color(&lab_style, lv_color_hex(0x7300FD));
    lv_obj_set_style_text_align(lab, LV_TEXT_ALIGN_CENTER, LV_STATE_DEFAULT); 
    lv_style_set_opa(&lab_style, 255);
    lv_style_set_border_color(&lab_style, lv_color_hex(0xFF0000));
    lv_style_set_border_width(&lab_style, 5);
    lv_style_set_border_opa(&lab_style, 255);
    lv_style_set_radius(&lab_style, 10);
    lv_style_set_text_color(&lab_style, lv_color_hex(0xFF0000));
    lv_style_set_text_font(&lab_style, &lv_my_font);
    lv_obj_add_style(lab, &lab_style, LV_STATE_DEFAULT);

    // 背景图
    lv_obj_t *img = lv_img_create(lv_scr_act());
    lv_img_set_src(img, "A:wang.bmp"); 
    lv_obj_set_pos(img,30,0);
    lv_obj_set_style_opa(img, 50, 0);

    // 右侧信息面板
    lv_obj_t *panel=lv_obj_create(lv_screen_active());
    lv_obj_set_size(panel,150,LV_PCT(100));
    lv_obj_align(panel,LV_ALIGN_RIGHT_MID,0,0);
    lv_obj_clear_flag(panel,LV_OBJ_FLAG_SCROLLABLE);

    //分数
    ui.score_label=lv_label_create(panel);
    lv_label_set_text(ui.score_label,"score:0");
    lv_obj_set_style_text_font(ui.score_label,&lv_font_montserrat_20,0);
    lv_obj_set_size(ui.score_label, 100, 60);
    lv_obj_set_pos(ui.score_label, 5, 30);

    //下一个方块预览
    lv_obj_t *next_label=lv_label_create(panel);
    lv_label_set_text(next_label,"next:");
    lv_obj_set_style_text_font(next_label,&lv_font_montserrat_20,0);
    lv_obj_set_size(next_label, 60, 80);
    lv_obj_set_pos(next_label, 5, 120);
    ui.next_block=lv_img_create(panel);
    lv_img_set_src(ui.next_block,"A:L.bmp");
    lv_obj_set_pos(ui.next_block, 5, 160);

    //速度
    ui.level_label=lv_label_create(panel);
    lv_label_set_text(ui.level_label,"speed:1");
    lv_obj_set_style_text_font(ui.level_label,&lv_font_montserrat_20,0);
    lv_obj_set_size(ui.level_label, 80, 60);
    lv_obj_set_pos(ui.level_label, 5, 400);

    //行数
    ui.lines_label=lv_label_create(panel);
    lv_label_set_text(ui.lines_label,"lines:0");
    lv_obj_set_style_text_font(ui.lines_label,&lv_font_montserrat_20,0);
    lv_obj_set_size(ui.lines_label, 60, 60);
    lv_obj_set_pos(ui.lines_label, 5, 500);

    // 初始化方块显示对象
    for(int y=0;y<20;y++)
    {
        for(int x=0;x<10;x++)
        {
            ui.block_imgs[y][x]=lv_img_create(ui.game_area);
            lv_obj_set_size(ui.block_imgs[y][x],BLOCK_SIZE,BLOCK_SIZE);
            lv_obj_set_pos(ui.block_imgs[y][x],x*BLOCK_SIZE,y*BLOCK_SIZE);
            lv_obj_add_flag(ui.block_imgs[y][x],LV_OBJ_FLAG_HIDDEN);
        }
    }

    // 创建控制按钮（只创建一次）
    lv_obj_t *but1=my_lv_init_button(lv_screen_active(),440,370,100,100,0x2691FA,0x000A03,"left");
    lv_obj_add_event_cb(but1, my_but1_event_cb, LV_EVENT_CLICKED, NULL);

    lv_obj_t *but2=my_lv_init_button(lv_screen_active(),640,370,100,100,0x2691FA,0x000A03,"right");
    lv_obj_add_event_cb(but2, my_but2_event_cb, LV_EVENT_CLICKED, NULL);

    lv_obj_t *but3=my_lv_init_button(lv_screen_active(),540,270,100,100,0x2691FA,0x000A03,"full");
    lv_obj_add_event_cb(but3, my_but3_event_cb, LV_EVENT_CLICKED, NULL);

    lv_obj_t *but4=my_lv_init_button(lv_screen_active(),530,470,120,100,0x2691FA,0x000A03,"rotate");
    lv_obj_add_event_cb(but4, my_but4_event_cb, LV_EVENT_CLICKED, NULL);
}

//检查方块状态
bool check_collision(int new_x, int new_y, int new_rotation)
{
    for (int y = 0; y < 4; y++) {
        for (int x = 0; x < 4; x++) {
            // 根据旋转状态获取方块的形状
            int block_value;
            switch (new_rotation % 4) {
                case 0:
                     block_value = THTROMINOS[game.current_piece][y][x]; 
                    break;
                case 1:
                     block_value = THTROMINOS[game.current_piece][x][3 - y];
                    break; // 右转90°
                case 2: 
                    block_value = THTROMINOS[game.current_piece][3 - y][3 - x];
                    break; // 180°
                case 3:   
                    block_value = THTROMINOS[game.current_piece][3 - x][y];
                    break; // 左转90°
            }
            if (block_value) {
                int bx = new_x + x;
                int by = new_y + y;
                 // 允许部分方块在顶部外（by < 0）
                if (bx < 0 || bx >= 10 || by >= 20) {
                    return true;
                }
                if (by >= 0 && game.board[by][bx] != EMPTY) {
                    return true;
                }
            }
        }
    }
    return false;
}

//计算方块的实际坐标
int get_block_pos(int* bx, int* by, int x, int y, int rotation, int piece_type)
{
    int offset_x = 0, offset_y = 0;
    
    // I型方块特殊处理
    if (piece_type == 2) { // I型
        if (rotation % 2 == 1) { // 竖向
            offset_x = -1; // 向左补偿1格
            offset_y = -1; // 向上补偿1格
        }
    }
    
    // 通用坐标转换
     switch (rotation & 3) {
        case 0: *bx = x;           *by = y;           break;
        case 1: *bx = game.x + (3 - (y - game.y)); *by = game.y + (x - game.x); break;
        case 2: *bx = game.x + (3 - (x - game.x)); *by = game.y + (3 - (y - game.y)); break;
        case 3: *bx = game.x + (y - game.y); *by = game.y + (3 - (x - game.x)); break;
    }
    return (*bx >= 0 && *bx < 10 && *by >= 0 && *by < 20);
}

//锁住方块（当方块触地或者接触到其他已经固定好的方块时）
void lock_piece()
{
     for (int y = 0; y < 4; y++) {
        for (int x = 0; x < 4; x++) {
            int block_value = THTROMINOS[game.current_piece][y][x];
            if (block_value) {
                int bx = game.x + x;
                int by = game.y + y;
                if (by < 0) {  // 如果有部分方块在顶部外，不允许锁定
                    return;
                }
            }
        }
    }
    for(int y=0;y<4;y++)
    {
        for(int x=0;x<4;x++)
        {
            int block_value;
            switch (game.rotation % 4) {
                case 0: block_value = THTROMINOS[game.current_piece][y][x]; break;
                case 1: block_value = THTROMINOS[game.current_piece][x][3 - y]; break; // 右转90°
                case 2: block_value = THTROMINOS[game.current_piece][3 - y][3 - x]; break; // 180°
                case 3: block_value = THTROMINOS[game.current_piece][3 - x][y]; break; // 左转90°
            }
            if (block_value) {
                int bx = game.x + x;
                int by = game.y + y;
                if (by >= 0 && by < 20 && bx >= 0 && bx < 10) {
                    game.board[by][bx] = game.current_piece;
                }
            }
        }
    }
}

//清除满了格子的一行
void clear_lines()
{
    int lines_cleared=0;

    for(int y=19;y>=0;y--)
    {
        bool line_full=true;
        for(int x=0;x<10;x++)
        {
            if(game.board[y][x]==EMPTY)
            {
                line_full=false;
                break;
            }
        }
        //如果下面的方块满了（消除）
        if(line_full)
        {
            lines_cleared++;
            for(int ny=y;ny>0;ny--)
            {
                memcpy(game.board[ny],game.board[ny-1],sizeof(game.board[0]));
            }
            //清除最顶行
            memset(game.board[0],EMPTY,sizeof(game.board[0]));
            y++;
        }
    }  
    if(lines_cleared>0)
    {
        //加分数
        game.score+=lines_cleared*lines_cleared*100;
        //加行数
        game.lines+=lines_cleared;

        game.level=(game.lines/10)+1;
        //游戏下落的速度（值越小则越快）
        game.fall_speed=1000-(game.level-1)*100;
        if(game.fall_speed<100)
        {
            game.fall_speed=100;
        }
    }
}

void update_next_preview()
{
    if(game.next_piece>=0&&game.next_piece<7)
    {
        lv_img_set_src(ui.next_block,BLOCK_IMAGES[game.next_piece]);
    }
    else
    {
        lv_img_set_src(ui.next_block,"A:1.bmp");
    }
}

//交接下一个方块并且判断游戏是否结束
void spawn_new_piece()
{
    game.current_piece=game.next_piece;
    game.next_piece=get_next_from_bag();
    game.x=(game.current_piece==2)?3:4;
    game.y=(game.current_piece==2)?-2:-1;
    game.rotation=0;
    update_next_preview();

    if(check_collision(game.x,game.y,game.rotation))
    {
         if (!check_collision(game.x+1, game.y, game.rotation)) {
            game.x++;
        } else {
        //游戏结束
            printf("GAME OVER!\n");
            game_over = true;
        }
    }
}

//移动方块
bool move_piece(int dx,int dy)
{
    if(!check_collision(game.x+dx,game.y+dy,game.rotation))
    {
        game.x+=dx;
        game.y+=dy;
        return true;
    }
    return false;
}


//左键
static void my_but1_event_cb(lv_event_t *e)
{
    pthread_mutex_lock(&game_mutex);
    move_piece(-1,0);
    pthread_mutex_unlock(&game_mutex);
}

//右键
static void my_but2_event_cb(lv_event_t *e)
{
    pthread_mutex_lock(&game_mutex);
    move_piece(1,0);
    pthread_mutex_unlock(&game_mutex);
}

//快速落键
static void my_but3_event_cb(lv_event_t *e)
{
    pthread_mutex_lock(&game_mutex);
    while(1) {
        if (!move_piece(0, 1)) {
            // 检查是否可以锁定
            bool can_lock = true;
            for (int y = 0; y < 4; y++) {
                for (int x = 0; x < 4; x++) {
                    if (THTROMINOS[game.current_piece][y][x] && 
                        (game.y + y) < 0) {
                        can_lock = false;
                        break;
                    }
                }
                if(!can_lock) break;
            }
            
            if (can_lock) {
                lock_piece();
                clear_lines();
                spawn_new_piece();
            }
            break;
        }
    }
    pthread_mutex_unlock(&game_mutex);
}

//旋转键
static void my_but4_event_cb(lv_event_t *e)
{
    pthread_mutex_lock(&game_mutex);
    rotate_piece();//旋转
    pthread_mutex_unlock(&game_mutex);
}